import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns


# 数据过滤和分箱处理函数
def filter_and_bin_data(df, col1, col2, col1_min=None, col1_max=None, bins=20):

    if col1_min is not None and col1_max is not None:
        # 过滤 col1 在指定范围内的数据
        filtered_df = df[(df[col1] >= col1_min) & (df[col1] <= col1_max)].copy()
    else:
        filtered_df = df.copy()

    # 对 col1 进行分箱
    filtered_df.loc[:, 'col1_bins'] = pd.cut(filtered_df[col1], bins=bins)

    # 对 col2 进行分箱，精确到小数点后5位
    col2_bin_edges = np.linspace(filtered_df[col2].min(), filtered_df[col2].max(), bins + 1)
    filtered_df.loc[:, 'col2_bins'] = pd.cut(filtered_df[col2], bins=col2_bin_edges)

    return filtered_df


# 分析各个 col1 分箱中 col2 的分布特点
def analyze_distribution(df, col2, col1_bin):
    # 过滤 col1_bins 列中值为 col1_bin 的行
    filtered_df = df[df['col1_bins'] == col1_bin]

    # 计算 col2 的描述性统计信息
    description = filtered_df[col2].describe()

    # 计算 col2 大于 0 的数量
    count_col2_gt_0 = (filtered_df[col2] > 0).sum()

    # 计算总数
    total_count = filtered_df[col2].count()

    # 计算大于 0 的数量占总数的比例
    proportion_col2_gt_0 = count_col2_gt_0 / total_count if total_count > 0 else 0

    return {
        "description": description,
        "proportion_col2_gt_0": proportion_col2_gt_0
    }


# 比较不同 col1 分箱间 col2 分布的差异
def compare_distributions(df, col2):
    plt.figure(figsize=(15, 10))
    sns.boxplot(x='col1_bins', y=col2, data=df)
    plt.xticks(rotation=90)
    plt.xlabel('col1 Bins')
    plt.ylabel(f'{col2} Distribution')
    plt.title(f'Comparison of {col2} Distribution across col1 Bins')
    plt.show()


# 进一步数据可视化
def plot_detailed_distributions(df, col2, bins_col2=20):
    col1_bins = df['col1_bins'].unique()
    fig, axes = plt.subplots(5, 2, figsize=(40, 30), sharex=True, sharey=True)
    axes = axes.flatten()

    for i, col1_bin in enumerate(col1_bins):
        filtered_df = df[df['col1_bins'] == col1_bin]

        counts, bins, patches = axes[i].hist(filtered_df[col2], range=(-0.1, 0.1), bins=bins_col2, edgecolor='black')

        for count, bin_edge, patch in zip(counts, bins, patches):
            if count > 0:
                bin_range = f'{bin_edge:.5f}-{bin_edge + (bins[1] - bins[0]):.5f}'
                axes[i].text(patch.get_x() + patch.get_width() / 2, count, f'{bin_range}\n{int(count)}',
                             ha='center', va='bottom', fontsize=8, color='black', rotation=90)

        axes[i].set_title(f'{col1_bin}&{col2}')
        axes[i].set_xlabel(col2)
        axes[i].set_ylabel('Frequency')

    plt.tight_layout()
    plt.show()


# 主函数，整合以上步骤
def detail_analyse(df, col1, col2, col1_min=None, col1_max=None, col1_bins=20, col2_bins=20):


    # 数据过滤和分箱处理
    filtered_df = filter_and_bin_data(df, col1, col2, col1_min, col1_max, col1_bins)

    # 获取分箱后的唯一值
    col1_bins = filtered_df['col1_bins'].unique()

    # 分析各个 col1 分箱中 col2 的分布特点
    for col1_bin in col1_bins:
        print(f'Distribution for {col1_bin}:')
        print(analyze_distribution(filtered_df, col2, col1_bin))
        print('\n')

    # 比较不同 col1 分箱间 col2 分布的差异
    # compare_distributions(filtered_df, col2)

    # 进一步数据可视化
    plot_detailed_distributions(filtered_df, col2, col2_bins)


# # 示例使用
# # 构建示例数据
# data = {
#     'col1': np.random.randint(0, 1000, 1000),
#     'col2': np.random.random(1000) * 1000
# }
#
# df = pd.DataFrame(data)
# main(df, 'col1', 'col2', col1_min=100, col1_max=900, bins=20)
